/*
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *    2010 year
 *    Author: Michael Khromov aka MikeDM (Mike D'Morto)
 *    E-Mail: mikedmorto@gmail.com
 */

#include "tspldb_mysql.h"
#include <QDebug>


bool Tspldb_mysql::qinit(const QStringList &cfgstr){
    // инициализация плагина.
    emit this->sigPutLog(PLUGIN_NAME,2,"Info: init");
    // устанавливаем метку инициации, в конце операции ее нужно будет инвертировать.

    // парсим параметры
    if(cfgstr.size()!=5){
        // параметров передано неверное количество. беда
        emit this->sigPutLog(PLUGIN_NAME,3,"Debug: test config string is failure");
        return false;
    }
    // вынимаем параметры и передаем их сразу создаваемому потоку.
    for(int i = 0 ; i < cfgstr.size() ; i ++){
        // ищем сервер
        if(QString(cfgstr.at(i)).split("=").at(0)=="server"){
            // сервер найден.
            this->dbServer=QString(cfgstr.at(i)).split("=").at(1);
        }
    }
    for(int i = 0 ; i < cfgstr.size() ; i ++){
        // ищем логин
        if(QString(cfgstr.at(i)).split("=").at(0)=="login"){
            // логин найден.
            this->dbLogin=QString(cfgstr.at(i)).split("=").at(1);
        }
    }
    for(int i = 0 ; i < cfgstr.size() ; i ++){
        // ищем пароль
        if(QString(cfgstr.at(i)).split("=").at(0)=="pass"){
            // сервер найден.
            this->dbPass=QString(cfgstr.at(i)).split("=").at(1);
        }
    }
    for(int i = 0 ; i < cfgstr.size() ; i ++){
        // ищем имя базы
        if(QString(cfgstr.at(i)).split("=").at(0)=="db"){
            // имя базы найдено.
            this->dbName=QString(cfgstr.at(i)).split("=").at(1);
        }
    }
    // создаем поток.
    emit this->sigPutLog(PLUGIN_NAME,3,"Debug: connect to server <"+this->dbServer+">"+
                             " use database <"+this->dbName+">"+
                             " as user <"+this->dbLogin+">");

    this->isInit=true;
    this->isInitErr=false;
    this->isInitOk=false;
    this->dt = new DbThread(this->dbServer,this->dbLogin,this->dbPass,this->dbName);
    connect(dt,SIGNAL(sigFinish(int,QSqlQuery*)),this,SLOT(slotDbThreadFinish(int,QSqlQuery*)),Qt::DirectConnection);
    connect(dt,SIGNAL(sigError(QString,QString)),SLOT(slotThErr(QString,QString)),Qt::DirectConnection);
    connect(dt,SIGNAL(sigThPutLog(QString,int,QString)),SLOT(slotThPutLog(QString,int,QString)),Qt::DirectConnection);
    connect(dt,SIGNAL(sigStartOkS(QString)),SLOT(slotQstartS(QString)),Qt::DirectConnection);
    connect(dt,SIGNAL(sigFinishS(QString,QSqlQuery*)),SLOT(slotDbThreadFinishS(QString,QSqlQuery*)),Qt::DirectConnection);
    connect(dt,SIGNAL(sigErrorS(QString,QString)),SLOT(slotThErrS(QString,QString)),Qt::DirectConnection);

    // уходим в сон и переодически проверяем состояние флагов.
    while(true){
        //sleep(1);

        if(this->isInitErr or this->isInitOk){
            break;
        }
    }
    // состояние флагов изменилось, тестим шо изменилось.
    if(this->isInitErr){
        // все просрали полимеры. отчитываемся об ошибке.
        emit this->sigPutLog(PLUGIN_NAME,3,"Debug: failure connect");
        return false;
    }

    // раз исполнение дошло досюда, значит все гуд.

    emit this->sigPutLog(PLUGIN_NAME,3,"Debug: success connect");
    this->isInit=false;

    return true;

}

/*
void Tspldb_mysql::refreshAq(){
// обвновить список доступных функций для плагинов
// реализовать при необходимости.
}
*/

//QString Tspldb_mysql::getPluginName(){
//
//}

void Tspldb_mysql::slotQexec(const QString pl_name,const QString & fname,const QList<QVariant> & parameters){
    // приняли данные на запрос. вот тут и начинаются пляски с бубуном.

    // здеся надо начать работать над след этапом.
    this->mPname=pl_name;
    this->mFname=fname;

    dt->putFun(this->mPname,this->mFname,parameters);

}

void Tspldb_mysql::slotDbThreadFinish(int id,QSqlQuery * ret){
    // проверяем если это инициализация, значит сохраняем указатель на результат в спец указатель а не передаем дальше
    // если это уже рабочая ситуация значит отдаем этот указатель дальше сигналом.
    if(this->isInit){
        // пришел ответ при инициализации
        this->isInitOk=true;
        //this->initret = ret;
    }else{
        // это уже другим плагинам, надо отдать сигналом.
        emit this->sigFinish(this->mPname,id,ret);
    }


}

void Tspldb_mysql::slotClear(int id){

    this->dt->clearID(id);
}

void Tspldb_mysql::slotThErr(const QString & plName ,const QString & errtext){
    // обрабатываем ошибку
    // проверяем если это инициализация, значит обшибко инициализации, устанавливаем флаг инит ишибки
    // если это уже рабочая ситуация значит отдаем этот указатель дальше сигналом.

    if(this->isInit){
        // пришел ответ при инициализации
        this->isInitErr=true;
    }else{
        // это уже другим плагинам, надо отдать сигналом.
        emit this->sigFinishErr(plName,errtext);
    }
}

void Tspldb_mysql::slotThPutLog(const QString &owner, int level, const QString &text){
    // передаем сигнал от потока в лог основного потока
    emit this->sigPutLog(owner,level,text);
}

// синхронный мать его режим, кровопийцо.
void Tspldb_mysql::slotQstartS(const QString & pl_name){
    // сообщаем второму потоку о добавлении в очередь еще одного плагина
    dt->putSinq(pl_name);

}
// запрос в базу в асинхронном режиме
void Tspldb_mysql::slotQexecS(const QString pl_name,const QString & fname,const QList<QVariant> & parameters){
// дергаем второй поток и ложим туда запрос
    this->dt->putFunS(pl_name,fname,parameters);
}
// сигнал окончания работы в синхронном режиме
void Tspldb_mysql::slotQstopS(const QString & pl_name){
    this->dt->stopSinq(pl_name);
}


void Tspldb_mysql::slotStartOkS(const QString & pl_name){
    // получили одобрение на начала синхронного режима с плагином. отдаем сигнал всем плагинам.
    emit this->sigRstartS(pl_name);
}

void Tspldb_mysql::slotDbThreadFinishS(const QString & pl_name, QSqlQuery * ret){
    // отдаем это сигналом удачи всем плагинам.
    emit this->sigFinishS(pl_name,ret);
}

void Tspldb_mysql::slotThErrS(const QString &pl_name, const QString &errtext){
    // отдаем сигнал неудачи всем плагинам
    emit this->sigFinishErrS(pl_name,errtext);
}

void Tspldb_mysql::slotStop(){
    // даем сигнал завершения работы с бд.
    this->dt->stopThread();
}
Q_EXPORT_PLUGIN2(TsIfaceDbPlugin,Tspldb_mysql)
